﻿Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Printing
Imports System.Drawing.Text
Imports System.IO
Imports System.Windows.Forms

Public Class PrintBarcodeDocument
    Inherits PrintDocument

    Const OFFSET_LINKS_IN_MM As Single = 10.0F
    Const OFFSET_BOVEN_IN_MM As Single = -2.0F

    Private _barcodes As List(Of String)
    Private _raster As Raster
    Private _margeBovenkantInMm As Single

    Public Sub New(ByVal barcodes As List(Of String), ByVal raster As Raster, ByVal margeBovenkantInCm As Double)
        _barcodes = barcodes
        _raster = raster
        _margeBovenkantInMm = Convert.ToSingle(margeBovenkantInCm) * 10.0F
    End Sub

    Protected Overloads Overrides Sub OnPrintPage(ByVal e As PrintPageEventArgs)
        MyBase.OnPrintPage(e)
        Dim gdiPage As Graphics = e.Graphics

        Dim realMarginBounds As RectangleF = GetRealMarginBoundsInMm(e)
        Dim leftMargin As Single = realMarginBounds.Left
        Dim topMargin As Single = realMarginBounds.Top
        Dim cellWidth As Single = Convert.ToSingle(realMarginBounds.Width / _raster.AantalKolommen)
        Dim cellHeight As Single = realMarginBounds.Height / _raster.AantalRijen

        Dim count As Integer = 0

        ' Druk elke barcode in het raster af
        For row As Integer = 0 To _raster.AantalRijen
            For column As Integer = 0 To _raster.AantalKolommen
                If (Not _raster.Selection(row, column)) Then Continue For
                Dim locationLeft As Single = leftMargin + OFFSET_LINKS_IN_MM + column * cellWidth
                Dim locationTop As Single = topMargin + OFFSET_BOVEN_IN_MM + row * cellHeight
                PrintBarcode(gdiPage, _barcodes(count), New PointF(locationLeft, locationTop))
                ' TODO: eventueel ook artikelnaam en prijs afdrukken
                count += 1
            Next
        Next
        e.HasMorePages = False ' altijd maar 1 blad
    End Sub

    Private Sub PrintBarcode(ByVal gdiPage As Graphics, ByVal barcode As String, ByVal location As PointF)
        'gdiPage.DrawString(barcode, _barcodeFont, Brushes.Black, locationLeft, locationTop)
        'gdiPage.DrawString(barcode, _numberFont, Brushes.Black, locationLeft, locationTop + _barcodeFont.Height)
        Dim ean13 As New Ean13Barcode(barcode)
        ean13.Scale = 1.3F
        ean13.DrawEan13Barcode(gdiPage, location)
    End Sub

    Private Function GetRealMarginBoundsInMm(ByVal e As PrintPageEventArgs) As RectangleF
        ' neem niet MarginBounds, want die is niet erg betrouwbaar
        Dim width As Single = e.PageBounds.Width * 2.54F / 10.0F ' zet om van 1/100 inch naar mm
        Dim height As Single = e.PageBounds.Height * 2.54F / 10.0F
        Dim bounds As New RectangleF(0, _margeBovenkantInMm, width, height - 2.0F * _margeBovenkantInMm)
        Return bounds
    End Function

    ' Volgende code wordt niet gebruikt, omdat wij geen margins gebruiken, 
    ' we gebruiken de volledige pagina om af te drukken.
    ' Als er grote printermargins zijn, dan kan het zijn dat er een stukje afgesneden wordt,
    ' maar dat vinden we niet erg (omdat de huidige printer zeer klein marges heeft).

    '' Adjust MarginBounds rectangle when printing based
    '' on the physical characteristics of the printer
    'Private Shared Function GetRealMarginBounds(ByVal e As PrintPageEventArgs, ByVal preview As Boolean) As Rectangle

    '    If preview Then
    '        Return e.MarginBounds
    '    End If

    '    ' Get printer's offsets
    '    Dim cx As Single = e.PageSettings.HardMarginX
    '    Dim cy As Single = e.PageSettings.HardMarginY

    '    ' Create the real margin bounds by scaling the offset
    '    ' by the printer resolution and then rescaling it
    '    ' back to 1/100 inch
    '    Dim marginBounds As Rectangle = e.MarginBounds
    '    Dim dpiX As Single = e.Graphics.DpiX
    '    Dim dpiY As Single = e.Graphics.DpiY
    '    marginBounds.Offset(CInt((-cx * 100 / dpiX)), CInt((-cy * 100 / dpiY)))
    '    Return marginBounds
    'End Function

    '' Get real page bounds based on printable area of the page
    'Private Shared Function GetRealPageBounds(ByVal e As PrintPageEventArgs, ByVal preview As Boolean) As Rectangle
    '    ' Return in units of 1/100th of an inch
    '    If preview Then
    '        Return e.PageBounds
    '    End If

    '    ' Translate to units of 1/100th of an inch
    '    Dim vpb As RectangleF = e.Graphics.VisibleClipBounds
    '    Dim bottomRight As PointF() = {New PointF(vpb.Size.Width, vpb.Size.Height)}
    '    e.Graphics.TransformPoints(CoordinateSpace.Device, CoordinateSpace.Page, bottomRight)
    '    Dim dpiX As Single = e.Graphics.DpiX
    '    Dim dpiY As Single = e.Graphics.DpiY
    '    Return New Rectangle(0, 0, CInt((bottomRight(0).X * 100 / dpiX)), CInt((bottomRight(0).Y * 100 / dpiY)))
    'End Function

    '<DllImport("gdi32.dll")> _
    'Private Shared Function GetDeviceCaps(ByVal hdc As IntPtr, ByVal index As DeviceCapsIndex) As Integer
    'End Function

    'Enum DeviceCapsIndex
    '    PhysicalOffsetX = 112
    '    PhysicalOffsetY = 113
    'End Enum

    '' Adjust MarginBounds rectangle when printing based on the physical characteristics of the printer
    'Private Shared Function GetRealMarginBounds(ByVal e As PrintPageEventArgs, ByVal preview As Boolean) As Rectangle
    '    If preview Then
    '        Return e.MarginBounds
    '    End If

    '    Dim cx As Integer = 0
    '    Dim cy As Integer = 0
    '    Dim hdc As IntPtr = e.Graphics.GetHdc()

    '    Try
    '        ' Both of these come back as device units and are not
    '        ' scaled to 1/100th of an inch
    '        cx = GetDeviceCaps(hdc, DeviceCapsIndex.PhysicalOffsetX)
    '        cy = GetDeviceCaps(hdc, DeviceCapsIndex.PhysicalOffsetY)
    '    Finally
    '        e.Graphics.ReleaseHdc(hdc)
    '    End Try

    '    ' Create the real margin bounds by scaling the offset
    '    ' by the printer resolution and then rescaling it
    '    ' back to 1/100th of an inch
    '    Dim marginBounds As Rectangle = e.MarginBounds
    '    Dim dpiX As Integer = CInt(e.Graphics.DpiX)
    '    Dim dpiY As Integer = CInt(e.Graphics.DpiY)
    '    marginBounds.Offset(Convert.ToInt32(-cx * 100 / dpiX), Convert.ToInt32(-cy * 100 / dpiY))
    '    Return marginBounds
    'End Function

End Class